/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package projet_compressionimage;

import java.awt.Color;
import java.awt.Graphics2D;
import java.awt.image.BufferedImage;
import java.util.ArrayList;

/**
 *
 * @author Colin
 */
public class NoeudCompose extends Noeud{
    private ArrayList<Noeud> noeuds;

    public NoeudCompose(String id) {
        super(id);
        this.noeuds= new ArrayList<Noeud>();
    }
    
    public void quadripartition(BufferedImage image) {
        int diviseur = 2;
        int width= image.getWidth();
        int height=image.getHeight();
        if(width>diviseur && height>diviseur && width%diviseur==0 && height%diviseur==0){
            int numNoeud=1;
            int widthDistance=image.getWidth()/diviseur;
            int heightDistance=image.getHeight()/diviseur;
            int i=0;
            while((i+heightDistance)<=image.getHeight()){
                //Découpage d'un morceau d'image
                //System.out.println(this.getId()+" "+String.valueOf(numNoeud));
                int j=0;
                while((j+widthDistance)<=image.getWidth() ){
                    BufferedImage imgDecoupee=image.getSubimage(j, i, heightDistance, widthDistance);
                    //Creation du NoeudComposé
                    NoeudCompose noeudCompose = new NoeudCompose(this.getId()+String.valueOf(numNoeud));

                    //Initialisation du Noeud à partir du morceau d'image découpé
                    noeudCompose.quadripartition(imgDecoupee);

                    //Ajout du Noeud à la liste des sous noeuds
                    this.addNoeud(noeudCompose);
                    
                    numNoeud++; //numéro du noeud
                    
                    j=j+widthDistance;
                    
                }

                i=i+heightDistance;
            }
        }else{
           initialiserFeuilles(image);
        }
        
    }

    public ArrayList<Noeud> getNoeuds() {
        return noeuds;
    }

    public void setNoeuds(ArrayList<Noeud> noeuds) {
        this.noeuds = noeuds;
    }
    public void addNoeud(Noeud noeud) {
        this.noeuds.add(noeud);
    }
    
    public void initialiserFeuilles(BufferedImage img){
        int numNoeud=1;
        for(int j=0;j<img.getHeight();j++){
            for(int k=0;k<img.getWidth();k++){
                Feuille feuille = new Feuille(this.getId()+String.valueOf(numNoeud) , img.getRGB(k, j));
                this.addNoeud(feuille);
                numNoeud++;
            }
        }
    }

    @Override
    public String toString() {
        return "\n"+getId()+": NoeudCompose:"+ noeuds ;
    }
    
    @Override
    Noeud compression(int compteurNiveau, int indicateurDiffMax) {
        // retourne le nombre de compression restantes
        //Parcour de l'arbre

        for(Noeud noeud: noeuds){
            noeuds.set(noeuds.indexOf(noeud), noeud.compression(compteurNiveau-1,indicateurDiffMax));
        }
        // Le retour du code récursif :FAIRE  LA COMPRESSION
        if(compteurNiveau==0){
            Noeud newNoeud = compresser(indicateurDiffMax);
            return newNoeud;
        }else{
            return this;
        }
    }
    



    @Override
    public Noeud compresser(int indicateurDiffMax) {
        ArrayList<Feuille> feuilles= new ArrayList<Feuille>();
        boolean aDesNoeudsComposes=false;
        
        for(Noeud noeud: noeuds){
                noeuds.set(noeuds.indexOf(noeud), noeud.compresser(indicateurDiffMax));
        }
        
        for(Noeud noeud: noeuds){
            if(noeud.getClass().getName().equals("projet_compressionimage.NoeudCompose")){
                aDesNoeudsComposes=true;
            }
        }
        if(aDesNoeudsComposes){
            return this;
        }else{ // Le retour du code récursif :FAIRE  LA COMPRESSION
            int[] tabMoyColors=calculMoyCouleurs();
            Color colorMoy=null;
            boolean diffMaxDepasse=false;
            for(Noeud noeud: noeuds){
                //System.out.println("couleur"+((Feuille)noeud).getCouleur());
                //System.out.println("Compar: "+(Math.abs(moyCouleurs-((Feuille)noeud).getCouleur())));
                if(!diffMaxDepasse){
                    int red =((Feuille)noeud).getCouleur().getRed();
                    int green =((Feuille)noeud).getCouleur().getGreen();
                    int blue =((Feuille)noeud).getCouleur().getBlue();
                    double sommeCarre=( Math.pow(red-tabMoyColors[0],2)+Math.pow(green-tabMoyColors[1],2)+Math.pow(blue-tabMoyColors[2],2));
                    colorMoy=new Color(tabMoyColors[0], tabMoyColors[1], tabMoyColors[2]);
                    int distance =(int)Math.sqrt(sommeCarre);
                    diffMaxDepasse=distance>indicateurDiffMax;
                }
            }
            if (diffMaxDepasse){
                return this;
            }else{
                Feuille f=new Feuille(this.getId(),colorMoy);
                return f;
            }
        }
    }
    @Override
    public Noeud compresser() {
        return compresser(1000000);
    }
    private int[] calculMoyCouleurs() {
        int[] tabMoy =new  int[3];
        int size= noeuds.size();
        if(size!=0){
            int sommeR=0;
            int sommeG=0;
            int sommeB=0;
            for(Noeud noeud: noeuds){
                sommeR=sommeR+(((Feuille)noeud).getCouleur().getRed());
                sommeG=sommeG+(((Feuille)noeud).getCouleur().getGreen());
                sommeB=sommeB+(((Feuille)noeud).getCouleur().getBlue());
                
            }
            tabMoy[0]=sommeR/size;
            tabMoy[1]=sommeG/size;
            tabMoy[2]=sommeB/size;

            return tabMoy;
        }else{
            return null;
        }
    }
    
    @Override
    BufferedImage reconstitutionImage(int distance, BufferedImage image, int coordX, int coordY) {
        int nb=0;
        int coordXInit=coordX;
        int coordYInit=coordY;
        for(Noeud noeud: noeuds){
            
            if(nb<2){
                    noeud.reconstitutionImage(distance/2,image,coordX,coordY);
                    coordX=coordX+(distance/2);

                
            }else if(nb==2){
                    coordX=coordXInit;
                    coordY=coordY+(distance/2);
                    
                    noeud.reconstitutionImage(distance/2,image,coordX,coordY);

            }else if(nb==3){
                coordX=coordX+(distance/2);
                noeud.reconstitutionImage(distance/2,image,coordX,coordY);
            }
           nb++;
        }
        
        return image;
    }

}
